package cn.amaake.magicplugin.nacos.util.parse;

import cn.amaake.magicplugin.nacos.util.AbstractConfigParse;
import com.alibaba.nacos.api.config.ConfigType;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.BaseConstructor;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.representer.Representer;
import org.yaml.snakeyaml.resolver.Resolver;

public class DefaultYamlConfigParse extends AbstractConfigParse {
    protected static final Logger LOGGER = LoggerFactory.getLogger(DefaultYamlConfigParse.class);
    private static final String YAML_ALLOW_COMPLEX_OBJECT = "yamlAllowComplexObject";

    public DefaultYamlConfigParse() {
    }

    private static boolean getYamlAllowComplexObject() {
        return Boolean.getBoolean("yamlAllowComplexObject");
    }

    protected static Yaml createYaml() {
        LoaderOptions loaderOptions = new LoaderOptions();
        loaderOptions.setAllowDuplicateKeys(false);
        Object constructor;
        if (getYamlAllowComplexObject()) {
            constructor = new Constructor(loaderOptions);
        } else {
            constructor = new SafeConstructor(loaderOptions);
        }

        DumperOptions dumperOptions = new DumperOptions();
        Representer representer = new Representer(dumperOptions);
        DefaultYamlConfigParse.LimitedResolver resolver = new DefaultYamlConfigParse.LimitedResolver();
        return new Yaml((BaseConstructor)constructor, representer, dumperOptions, loaderOptions, resolver);
    }

    protected static boolean process(DefaultYamlConfigParse.MatchCallback callback, Yaml yaml, String content) {
        int count = 0;
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Loading from YAML: " + content);
        }

        Iterator var4 = yaml.loadAll(content).iterator();

        while(var4.hasNext()) {
            Object object = var4.next();
            if (object != null && process(asMap(object), callback)) {
                ++count;
            }
        }

        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Loaded " + count + " document" + (count > 1 ? "s" : "") + " from YAML resource: " + content);
        }

        return count > 0;
    }

    protected static boolean process(Map<String, Object> map, DefaultYamlConfigParse.MatchCallback callback) {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Merging document (no matchers set): " + map);
        }

        callback.process(getFlattenedMap(map));
        return true;
    }

    protected static Map<String, Object> asMap(Object object) {
        Map<String, Object> result = new LinkedHashMap();
        if (!(object instanceof Map)) {
            result.put("document", object);
            return result;
        } else {
            Map<Object, Object> map = (Map)object;
            Iterator var3 = map.entrySet().iterator();

            while(var3.hasNext()) {
                Map.Entry<Object, Object> entry = (Map.Entry)var3.next();
                Object key = entry.getKey();
                Object value = entry.getValue();
                if (value instanceof Map) {
                    value = asMap(value);
                }

                if (key instanceof CharSequence) {
                    result.put(key.toString(), value);
                } else {
                    result.put("[" + key.toString() + "]", value);
                }
            }

            return result;
        }
    }

    protected static Map<String, Object> getFlattenedMap(Map<String, Object> source) {
        Map<String, Object> result = new LinkedHashMap();
        buildFlattenedMap(result, source, (String)null);
        return result;
    }

    protected static void buildFlattenedMap(Map<String, Object> result, Map<String, Object> source, String path) {
        Iterator var3 = source.entrySet().iterator();

        while(true) {
            while(var3.hasNext()) {
                Map.Entry<String, Object> entry = (Map.Entry)var3.next();
                String key = (String)entry.getKey();
                if (!StringUtils.isBlank(path)) {
                    if (key.startsWith("[")) {
                        key = path + key;
                    } else {
                        key = path + '.' + key;
                    }
                }

                Object value = entry.getValue();
                if (value instanceof String) {
                    result.put(key, value);
                } else if (value instanceof Map) {
                    Map<String, Object> map = (Map)value;
                    buildFlattenedMap(result, map, key);
                } else if (value instanceof Collection) {
                    Collection<Object> collection = (Collection)value;
                    int count = 0;
                    Iterator var9 = collection.iterator();

                    while(var9.hasNext()) {
                        Object object = var9.next();
                        buildFlattenedMap(result, Collections.singletonMap("[" + count++ + "]", object), key);
                    }
                } else {
                    result.put(key, value != null ? value.toString() : "");
                }
            }

            return;
        }
    }

    public Map<String, Object> parse(String configText) {
        final AtomicReference<Map<String, Object>> result = new AtomicReference();
        process(new DefaultYamlConfigParse.MatchCallback() {
            public void process(Map<String, Object> map) {
                result.set(map);
            }
        }, createYaml(), configText);
        return (Map)result.get();
    }

    public String processType() {
        return ConfigType.YAML.getType();
    }

    private static class LimitedResolver extends Resolver {
        private LimitedResolver() {
        }

        public void addImplicitResolver(Tag tag, Pattern regexp, String first) {
            if (tag != Tag.TIMESTAMP) {
                super.addImplicitResolver(tag, regexp, first);
            }
        }
    }

    protected interface MatchCallback {
        void process(Map<String, Object> var1);
    }
}